In notebook 5 we examined how the fringe transmission of a point source changes at different locations on the PSF. Where do the extended source fringes stand with respect to this change in transmission? In Notebook 1 - Test 3 the extended source fringes were shown not to move. Let's look at that again.
from IPython.display import HTML
HTML('''<script>
code_show=true;
function code_toggle() {
if (code_show){
$('div.input').hide();
} else {
$('div.input').show();
}
code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
The raw code for this IPython notebook is by default hidden for easier reading.
To toggle on/off the raw code, click <a href="javascript:code_toggle()">here</a>.''')
# import modules
import funcs
import mrsobs
import numpy as np
from matplotlib import pyplot as plt
plt.style.use('presentation')
%matplotlib notebook
import warnings
warnings.simplefilter('ignore')
We load the images for one band of the MRS for different kinds of sources, including:
Additionally the pixel-to-wavelength calibration map and the pixel-to-along-slice position map are imported.
# Define paths to data
workDir = '/Users/ioannisa/Desktop/python/miri_devel/'
cdpDir = workDir+'cdp_data/'
d2cMapDir = workDir+'distortionMaps/'
lvl2path = workDir+'FM_data/LVL2/'
# Get data
band = '1A'
ext_source_sci,ext_source_bkg = mrsobs.FM_MTS_BB_extended_source(lvl2path,band,bb_temp='800K')
ext_etal_source_sci,ext_etal_source_bkg = mrsobs.FM_MTS_800K_BB_extended_source_through_etalon(lvl2path,band,etalon='ET1A')
point_source_sci_p1,point_source_bkg_p1 = mrsobs.FM_MTS_800K_BB_MRS_OPT_06_raster(lvl2path,position='middle',pointing='P1')
# Get wavelength calibration pixel map
d2cMaps = funcs.load_obj('d2cMaps_band{}'.format(band),path=d2cMapDir)
lambdaMap = d2cMaps['lambdaMap']
lambdaMap[lambdaMap==0] = np.nan
alphaMap = d2cMaps['alphaMap']
nslices = d2cMaps['nslices']
We subtract background exposures where available.
# perform transform
ext_source_bkgsubtr = ext_source_sci-ext_source_bkg
ext_etal_source_bkgsubtr = ext_etal_source_sci-ext_etal_source_bkg
point_source_p1_bkgsubtr = point_source_sci_p1-point_source_bkg_p1
We perform an even-odd row signal correction to the data (caused by the read-out pattern of MIRI detector pixel rows).
ext_source_oddevencorr = funcs.OddEvenRowSignalCorrection(ext_source_bkgsubtr)
ext_etal_source_oddevencorr = funcs.OddEvenRowSignalCorrection(ext_etal_source_bkgsubtr)
point_source_p1_oddevencorr = funcs.OddEvenRowSignalCorrection(point_source_p1_bkgsubtr)
Much like in notebook 5 we take the three slices that contain the PSF (slices with largest signal), determine the pixel trace that contains the peak of the PSF, and then take the two traces on the left and the right to probe the sides of the PSF. The same positions are used to evaluate the extended source fringes.
# Pixel trace in MRS slice
ypos_sourcecenterslice,xpos_sourcecenterslice = funcs.detpixel_trace_compactsource(point_source_p1_oddevencorr,band,d2cMaps,offset_slice=0)
ypos_nearbyslice1,xpos_nearbyslice1 = funcs.detpixel_trace_compactsource(point_source_p1_oddevencorr,band,d2cMaps,offset_slice=-1)
ypos_nearbyslice2,xpos_nearbyslice2 = funcs.detpixel_trace_compactsource(point_source_p1_oddevencorr,band,d2cMaps,offset_slice=1)
xpos_offsets = [-2,-1,0,1,2]
Note that the etalon and point source plots are the same as in Notebook 5. We introduce two new plots, one for the fringe analysis of the extended source, and one where the extended and point source fringe transmissions are compared.
# normalize signal
pointsource_slice6_norm,pointsource_slice7_norm,pointsource_slice8_norm = [{} for i in range(3)]
for xpos_offset in xpos_offsets:
pointsource_slice6_norm['offset'+str(xpos_offset)] = funcs.norm_fringe(point_source_p1_oddevencorr[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset],thres=0,min_dist=6,k=1,ext=3)
pointsource_slice7_norm['offset'+str(xpos_offset)] = funcs.norm_fringe(point_source_p1_oddevencorr[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset],thres=0,min_dist=6,k=1,ext=3)
pointsource_slice8_norm['offset'+str(xpos_offset)] = funcs.norm_fringe(point_source_p1_oddevencorr[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset],thres=0,min_dist=6,k=1,ext=3)
extsource_slice6_norm,extsource_slice7_norm,extsource_slice8_norm = [{} for i in range(3)]
for xpos_offset in xpos_offsets:
extsource_slice6_norm['offset'+str(xpos_offset)] = funcs.norm_fringe(ext_source_oddevencorr[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset],thres=0,min_dist=6,k=3,ext=3)
extsource_slice7_norm['offset'+str(xpos_offset)] = funcs.norm_fringe(ext_source_oddevencorr[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset],thres=0,min_dist=6,k=3,ext=3)
extsource_slice8_norm['offset'+str(xpos_offset)] = funcs.norm_fringe(ext_source_oddevencorr[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset],thres=0,min_dist=6,k=3,ext=3)
# average of extended source normalized signals
extsource_slice6_norm_avg,extsource_slice7_norm_avg,extsource_slice8_norm_avg = np.zeros(3)
for xpos_offset in xpos_offsets:
extsource_slice6_norm_avg += extsource_slice6_norm['offset'+str(xpos_offset)][0]/extsource_slice6_norm['offset'+str(xpos_offset)][2]
extsource_slice7_norm_avg += extsource_slice7_norm['offset'+str(xpos_offset)][0]/extsource_slice7_norm['offset'+str(xpos_offset)][2]
extsource_slice8_norm_avg += extsource_slice8_norm['offset'+str(xpos_offset)][0]/extsource_slice8_norm['offset'+str(xpos_offset)][2]
extsource_slice6_norm_avg /= len(xpos_offsets)
extsource_slice7_norm_avg /= len(xpos_offsets)
extsource_slice8_norm_avg /= len(xpos_offsets)
fig,axs = plt.subplots(2,1,figsize=(18,8))
axs[0].set_title('Extended etalon data slice 6')
for xpos_offset in xpos_offsets:
for plot in range(2):
axs[plot].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset],ext_etal_source_oddevencorr[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset],label='xpos offset {}'.format(xpos_offset))
axs[plot].set_xlabel('Wavelength [micron]')
axs[plot].set_ylabel('Signal [DN/sec]')
axs[plot].legend(loc='upper right',fontsize=10)
axs[0].set_xlim(4.88,5.77)
axs[0].set_ylim(0)
axs[1].set_xlim(5.196,5.274)
axs[1].set_ylim(0)
plt.tight_layout()
fig,axs = plt.subplots(3,1,figsize=(18,13))
axs[0].set_title('Point source slice 6')
axs[0].vlines(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1][pointsource_slice6_norm['offset0'][1]],0,2.5,alpha=0.4,label='xpos offset 0 fringe peaks')
for xpos_offset in xpos_offsets:
axs[0].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset],pointsource_slice6_norm['offset'+str(xpos_offset)][0],label='xpos offset {}'.format(xpos_offset))
axs[0].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset],pointsource_slice6_norm['offset'+str(xpos_offset)][2])
norm_transmission = pointsource_slice6_norm['offset'+str(xpos_offset)][0]/pointsource_slice6_norm['offset'+str(xpos_offset)][2]
sel = (norm_transmission>0.7) & (norm_transmission<1.05)
axs[1].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].vlines(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1][pointsource_slice6_norm['offset0'][1]],0.7,1.05,alpha=0.4,label='xpos offset 0 fringe peaks')
axs[0].set_ylim(0,2.5)
axs[2].set_xlim(5.303,5.405)
axs[2].set_ylim(0.7,1.05)
axs[0].set_ylabel('Signal [DN/sec]')
axs[1].set_ylabel('Normalized signal')
axs[2].set_ylabel('Normalized signal')
for plot in range(2):
axs[plot].set_xlim(4.88,5.77)
for plot in range(3):
axs[plot].set_xlabel('Wavelength [micron]')
axs[plot].legend(loc='upper right',fontsize=10)
plt.tight_layout()
fig,axs = plt.subplots(3,1,figsize=(18,13))
axs[0].set_title('Extended source slice 6')
axs[0].vlines(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1][extsource_slice6_norm['offset0'][1]],22,36,alpha=0.4,label='xpos offset 0 fringe peaks')
for xpos_offset in xpos_offsets:
axs[0].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset],extsource_slice6_norm['offset'+str(xpos_offset)][0],label='xpos offset {}'.format(xpos_offset))
axs[0].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset],extsource_slice6_norm['offset'+str(xpos_offset)][2])
norm_transmission = extsource_slice6_norm['offset'+str(xpos_offset)][0]/extsource_slice6_norm['offset'+str(xpos_offset)][2]
sel = (norm_transmission>0.87) & (norm_transmission<1.05)
axs[1].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],extsource_slice6_norm_avg[sel],'k',linestyle='dashed',label='average profile')
axs[2].vlines(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1][extsource_slice6_norm['offset0'][1]],0.85,1.05,alpha=0.4,label='xpos offset 0 fringe peaks')
axs[0].set_ylim(22,36)
axs[2].set_xlim(5.303,5.405)
axs[2].set_ylim(0.85,1.05)
axs[0].set_ylabel('Signal [DN/sec]')
axs[1].set_ylabel('Normalized signal')
axs[2].set_ylabel('Normalized signal')
for plot in range(2):
axs[plot].set_xlim(4.88,5.77)
for plot in range(3):
axs[plot].set_xlabel('Wavelength [micron]')
axs[plot].legend(loc='upper right',fontsize=10)
plt.tight_layout()
# let's look at the results
fig,axs = plt.subplots(3,1,figsize=(18,13))
for xpos_offset in xpos_offsets:
norm_transmission = pointsource_slice6_norm['offset'+str(xpos_offset)][0]/pointsource_slice6_norm['offset'+str(xpos_offset)][2]
sel = (norm_transmission>0.7) & (norm_transmission<1.05)
axs[0].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[1].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],norm_transmission[sel]/extsource_slice6_norm_avg[sel],label='xpos offset {}'.format(xpos_offset))
axs[1].vlines(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1][pointsource_slice6_norm['offset0'][1]],0.7,1.35,alpha=0.4,label='xpos offset 0 fringe peaks')
axs[2].hlines([0.8,1.1],4.88,5.77,linestyle='dashed')
axs[2].hlines(1,4.88,5.77,'gray',alpha=0.4,linestyle='dashed')
axs[0].set_xlim(4.88,5.77)
axs[1].set_xlim(5.303,5.405)
axs[2].set_xlim(5.303,5.405)
for plot in range(2):
axs[plot].plot(lambdaMap[ypos_nearbyslice1,xpos_nearbyslice1+xpos_offset][sel],extsource_slice6_norm_avg[sel],'k',linestyle='dashed',label='average extended source fringe profile')
axs[plot].set_ylim(0.7,1.35)
axs[plot].set_xlabel('Wavelength [micron]')
axs[plot].set_ylabel('Normalized signal')
axs[plot].legend(loc='upper right',fontsize=10)
axs[2].set_xlabel('Wavelength [micron]')
axs[2].set_ylabel('Residuals')
axs[2].set_title('Ratio : point fringe /avg_extended fringe')
axs[2].legend(loc='upper right',fontsize=10)
plt.tight_layout()
Let's quickly look at the other slices (refer to Notebook 5 for the omitted etalon and point source plots).
fig,axs = plt.subplots(3,1,figsize=(18,13))
axs[0].set_title('Extended source slice 7')
axs[0].vlines(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice][extsource_slice7_norm['offset0'][1]],22,36,alpha=0.4,label='xpos offset 0 fringe peaks')
for xpos_offset in xpos_offsets:
axs[0].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset],extsource_slice7_norm['offset'+str(xpos_offset)][0],label='xpos offset {}'.format(xpos_offset))
axs[0].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset],extsource_slice7_norm['offset'+str(xpos_offset)][2])
norm_transmission = extsource_slice7_norm['offset'+str(xpos_offset)][0]/extsource_slice7_norm['offset'+str(xpos_offset)][2]
sel = (norm_transmission>0.87) & (norm_transmission<1.05)
axs[1].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset][sel],extsource_slice7_norm_avg[sel],'k',linestyle='dashed',label='average profile')
axs[2].vlines(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice][extsource_slice7_norm['offset0'][1]],0.85,1.05,alpha=0.4,label='xpos offset 0 fringe peaks')
axs[0].set_ylim(22,36)
axs[2].set_xlim(5.342,5.443)
axs[2].set_ylim(0.85,1.05)
axs[0].set_ylabel('Signal [DN/sec]')
axs[1].set_ylabel('Normalized signal')
axs[2].set_ylabel('Normalized signal')
for plot in range(2):
axs[plot].set_xlim(4.88,5.77)
for plot in range(3):
axs[plot].set_xlabel('Wavelength [micron]')
axs[plot].legend(loc='upper right',fontsize=10)
plt.tight_layout()
fig,axs = plt.subplots(3,1,figsize=(18,13))
for xpos_offset in xpos_offsets:
norm_transmission = pointsource_slice7_norm['offset'+str(xpos_offset)][0]/pointsource_slice7_norm['offset'+str(xpos_offset)][2]
sel = (norm_transmission>0.7) & (norm_transmission<1.05)
axs[0].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[1].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset][sel],norm_transmission[sel]/extsource_slice7_norm_avg[sel],label='xpos offset {}'.format(xpos_offset))
axs[1].vlines(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice][pointsource_slice7_norm['offset0'][1]],0.7,1.35,alpha=0.4,label='xpos offset 0 fringe peaks')
axs[2].hlines([0.73,1.08],4.88,5.77,linestyle='dashed')
axs[2].hlines(1,4.88,5.77,'gray',alpha=0.4,linestyle='dashed')
axs[0].set_xlim(4.88,5.77)
axs[1].set_xlim(5.342,5.443)
for plot in range(2):
axs[plot].plot(lambdaMap[ypos_sourcecenterslice,xpos_sourcecenterslice+xpos_offset][sel],extsource_slice7_norm_avg[sel],'k',linestyle='dashed',label='average extended source fringe profile')
axs[plot].set_ylim(0.7,1.35)
axs[plot].set_xlabel('Wavelength [micron]')
axs[plot].set_ylabel('Normalized signal')
axs[plot].legend(loc='upper right',fontsize=10)
axs[2].set_xlim(5.342,5.443)
axs[2].set_xlabel('Wavelength [micron]')
axs[2].set_ylabel('Residuals')
axs[2].set_title('Ratio : point fringe /avg_extended fringe')
axs[2].legend(loc='upper right',fontsize=10)
plt.tight_layout()
Let's look at the last slice.
fig,axs = plt.subplots(3,1,figsize=(18,13))
axs[0].set_title('Extended source slice 8')
axs[0].vlines(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2][extsource_slice8_norm['offset0'][1]],22,36,alpha=0.4,label='xpos offset 0 fringe peaks')
for xpos_offset in xpos_offsets:
axs[0].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset],extsource_slice8_norm['offset'+str(xpos_offset)][0],label='xpos offset {}'.format(xpos_offset))
axs[0].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset],extsource_slice8_norm['offset'+str(xpos_offset)][2])
norm_transmission = extsource_slice8_norm['offset'+str(xpos_offset)][0]/extsource_slice8_norm['offset'+str(xpos_offset)][2]
sel = (norm_transmission>0.87) & (norm_transmission<1.05)
axs[1].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset][sel],extsource_slice8_norm_avg[sel],'k',linestyle='dashed',label='average profile')
axs[2].vlines(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2][extsource_slice8_norm['offset0'][1]],0.85,1.05,alpha=0.4,label='xpos offset 0 fringe peaks')
axs[0].set_ylim(22,36)
axs[2].set_xlim(5.342,5.443)
axs[2].set_ylim(0.85,1.05)
axs[0].set_ylabel('Signal [DN/sec]')
axs[1].set_ylabel('Normalized signal')
axs[2].set_ylabel('Normalized signal')
for plot in range(2):
axs[plot].set_xlim(4.88,5.77)
for plot in range(3):
axs[plot].set_xlabel('Wavelength [micron]')
axs[plot].legend(loc='upper right',fontsize=10)
plt.tight_layout()
fig,axs = plt.subplots(3,1,figsize=(18,13))
for xpos_offset in xpos_offsets:
norm_transmission = pointsource_slice8_norm['offset'+str(xpos_offset)][0]/pointsource_slice8_norm['offset'+str(xpos_offset)][2]
sel = (norm_transmission>0.7) & (norm_transmission<1.05)
axs[0].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[1].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset][sel],norm_transmission[sel],label='xpos offset {}'.format(xpos_offset))
axs[2].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset][sel],norm_transmission[sel]/extsource_slice8_norm_avg[sel],label='xpos offset {}'.format(xpos_offset))
axs[1].vlines(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2][pointsource_slice8_norm['offset0'][1]],0.7,1.35,alpha=0.4,label='xpos offset 0 fringe peaks')
axs[2].hlines([0.765,1.08],4.88,5.77,linestyle='dashed')
axs[2].hlines(1,4.88,5.77,'gray',alpha=0.4,linestyle='dashed')
axs[0].set_xlim(4.88,5.77)
axs[1].set_xlim(5.342,5.443)
for plot in range(2):
axs[plot].plot(lambdaMap[ypos_nearbyslice2,xpos_nearbyslice2+xpos_offset][sel],extsource_slice8_norm_avg[sel],'k',linestyle='dashed',label='average extended source fringe profile')
axs[plot].set_ylim(0.7,1.35)
axs[plot].set_xlabel('Wavelength [micron]')
axs[plot].set_ylabel('Normalized signal')
axs[plot].legend(loc='upper right',fontsize=10)
axs[2].set_xlim(5.342,5.443)
axs[2].set_ylim(0.7,1.15)
axs[2].set_xlabel('Wavelength [micron]')
axs[2].set_ylabel('Residuals')
axs[2].set_title('Ratio : point fringe /avg_extended fringe')
axs[2].legend(loc='upper right',fontsize=10)
plt.tight_layout()
How do we link the amplitude, frequency, and phase of the fringe transmissions, of the different optical stimuli, to (apparent) optical properties of the interfering resonator? Being able to do so would permit us to assess the possible causes for the transmission discrepancies.